home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
yase.arc
/
EDIT3.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-12-13
|
15KB
|
448 lines
******************************************************************
* COPYRIGHT (C) 1986 by Donald Krantz and James Stanley
* - Note: This is a real, live, actual, registered copyright,
* and should be treated as such. This source code is from
* the book "68000 Assembly Language", Krantz and Stanley,
* Addison-Wesley Publishing Company, Reading, MA, 1986.
*
* Permission granted by the authors for non-commercial use
* in programs released to the public domain, as long as this
* copyright notice remains attached and visible.
*
*****************************************************************
* Editor Dispatcher
xref prtscr,stats,_getkey,sync_curs,case,cursor
xref _keyhit,group_1,group_2,group_4,refind,errors
xref prompt
xdef up,down,right,left,down_page,up_page,del_left
xdef toggle,eol,sol,dirty
xdef edit
#edit.h
#cursor.h
****************************************************************
* EDIT - Main editor dispatcher and executive.
edit:
bsr _keyhit * see if we're busy
tst.w d0 * d0 is nonzero if we're busy
bne sk1exec * we skip refresh if busy
bsr align_scr * make sure cursor's on screen
bsr prtscr * Print current buffer
bsr stats * Print editing stats
move.w ed_err(a5),d0 * Get edit error flag
ext.l d0 * make into longword
lsl.l #2,d0 * multiply by four
move.l #errors,a0 * get error message lookup table
add.l d0,a0 * get offset
move.l (a0),a0 * get error string address
bsr prompt * output message (or blank old)
clr.w ed_err(a5) * mark "no errors"
sk1exec:
move.w scr_row(a5),-(a7) put cursor where it belongs
move.w scr_col(a5),-(a7)
bsr cursor
addq.l #4,a7 * adjust stack
bsr sync_curs * Put cursor where it belongs
bsr _getkey * get input
ext.w d0 * make into a word
move.l #dispatch,a0 * load up case table
bsr case * perform required operation
bra edit * repeat
*****************************************************************
* Top Level Editor Dispatch Table
dispatch:
dc.w 23 * Number of valid options
dc.w tab * Tab
dc.l in_chr
dc.w 0 * PC cursor key prefix
dc.l group_4
dc.w c_up * Cursor up one line
dc.l up
dc.w c_down * Cursor down one line
dc.l down
dc.w c_right * Cursor one char right
dc.l right
dc.w c_left * Cursor one char left
dc.l left
dc.w c_w_right * Cursor one word right
dc.l w_right
dc.w c_w_left * Cursor one word left
dc.l w_left
dc.w return * Return Key
dc.l ret
dc.w backsp * Backspace Key
dc.l left
dc.w left_del * Left Delete Character
dc.l del_left
dc.w right_del * Right Delete Character
dc.l del_right
dc.w lit_prefix * Literal Insertion Prefix
dc.l prefix
dc.w word_del * Right Delete Word
dc.l del_word
dc.w group1 * Group 1 Commands prefix
dc.l group_1
dc.w group2 * Group 2 Commands prefix
dc.l group_2
dc.w group3 * Group 3 Commands prefix
dc.l group_3
dc.w line_del * Delete line key
dc.l del_line
dc.w page_up * Page Up key
dc.l up_page
dc.w page_down * Page Down key
dc.l down_page
dc.w repeat * Repeat Find key
dc.l refind
dc.w insert_key * Insert Toggle Key
dc.l toggle
dc.w ins_line * Insert Line key
dc.l line_ins
dc.l ins_chr * default - insert character
*****************************************************************
* GROUP_3 - group 3 (window) commands
group_3:
move.l #-1,d0 * Set "continue" flag
addq.l #4,a7 * lift one return address
rts * return to caller of "edit"
*****************************************************************
* RIGHT - Moves cursor right. Returns byte moved in D0.
right:
clr.w d0 * setup fake return value
move.l e_gap(a5),a0 * check if we can move left
cmp.l e_buf(a5),a0 * we look at the end of buffer
bgt sk0_rt * jump if we can't move
move.l b_gap(a5),a1 * get destination for char
move.b (a0),d0 * save the byte to return it
cmp.b #10,(a0) * check for line crossing
bne sk1_rt * skip if not line crossing
addq.w #1,log_lin(a5) * add one to line count
sk1_rt:
move.b (a0)+,(a1)+ * move the byte across gap
addq.l #1,e_gap(a5) * move end pointer
addq.l #1,b_gap(a5) * move start pointer
sk0_rt:
rts
*****************************************************************
* LEFT - moves cursor left. Returns byte moved in D0.
left:
clr.w d0 * setup fake return value
move.l b_gap(a5),a0 * check if we can move right
cmp.l b_buf(a5),a0 * we look at the start of buffer
ble sk0_lf * jump if we can't move
move.l e_gap(a5),a1 * get destination for char
move.b -(a0),-(a1) * move the byte across gap
move.b (a1),d0 * save the byte to return it
cmp.b #10,(a1) * check for line crossing
bne sk1_lf * jump if not line crossing
subq.w #1,log_lin(a5) * bump down current line counter
sk1_lf:
subq.l #1,e_gap(a5) * move end pointer
subq.l #1,b_gap(a5) * move start pointer
sk0_lf:
rts
*****************************************************************
* UP - moves cursor up one line
up:
bsr sol * move to start of this line
bsr left * move back over newline
bsr sol * move to start of this line
bsr outline * put cursor out into line
rts
*****************************************************************
* DOWN - moves cursor down one line
down:
bsr eol * move to end of line
bsr right * jump over newline
bsr outline * put cursor out into line
rts
*****************************************************************
* W_RIGHT - Moves the cursor one word right
w_right:
bsr right * start right
tst.b d0 * look for end-of-file
beq sk0_wr * outta here if end of file
bsr isdelim * look for delimiter
tst.b d0 * check return value
beq w_right * loop until we find delimiter
lp0_wr:
bsr right * start right
tst.b d0 * look for end-of-file
beq sk0_wr * outta here if end of file
bsr isdelim * look for delimiter
tst.b d0 * check return value
bne lp0_wr * loop until we finish delimiters
bsr left * back off one
sk0_wr:
rts
*****************************************************************
* W_LEFT - move the cursor one word to the left
w_left:
bsr left * start left
tst.b d0 * look for start-of-file
beq sk0_wl * outta here if start of file
bsr isdelim * look for delimiter
tst.b d0 * check return value
bne w_left * loop while no delimiter
lp0_wl:
bsr left * start left
tst.b d0 * look for start-of-file
beq sk0_wl * outta here if start of file
bsr isdelim * look for delimiter
tst.b d0 * check return value
beq lp0_wl * loop until we hit delimiters
bsr right * back off one
sk0_wl:
rts
*****************************************************************
* UP_PAGE - moves cursor up one page
up_page:
move.w w_rows(a5),d1 * calculate number of lines
subq.w #2,d1 * leave two rows for context
bgt sk0_up * check if we still have some
clr.w d1 * we need at least one...
sk0_up:
bsr sol * move to start of this line
bsr left * back up over newline
tst.w d0 * check for top of file
beq sk1_up * break out if top of file
dbra d1,sk0_up * loop 'lines' times
bsr right * move over current newline
sk1_up:
bsr outline * move cursor out into line
rts
*****************************************************************
* DOWN_PAGE - moves cursor down one page
down_page:
move.w w_rows(a5),d1 * calculate number of lines
subq.w #3,d1 * leave two rows for context
bgt sk0_dn * check if we still have some
move.w #0,d1 * we need at least one...
sk0_dn:
bsr eol * move to end of this line
bsr right * skip over newline
dbra d1,sk0_dn * loop 'lines' times
bsr sol * move to start of this line
bsr outline * move cursor out into line
rts
*****************************************************************
* DEL_RIGHT - delete one character to the right
del_right:
bsr right * try to move right
tst.b d0 * is there anything there?
beq sk0dr * jump if not
subq.l #1,b_gap(a5) * delete character
bsr dirty * set modified flags
sk0dr:
rts
*****************************************************************
* DEL_LEFT - delete one character to the left
del_left:
bsr left * try to move left
tst.b d0 * is there anything there?
beq sk0dl * jump if not
addq.l #1,e_gap(a5) * delete character
bsr dirty * set modified flags
sk0dl:
rts
*****************************************************************
* DEL_LINE - deletes line that cursor is on
del_line:
bsr sol * move to start of this line
move.l b_gap(a5),-(a7) * save gap start address
bsr eol * move to end of this line
bsr right * and one more for newline
cmp.b #10,d0 * make sure we got a newline
bne sk0ld * jump if not
subq.w #1,log_lin(a5) * adjust line count
sk0ld:
move.l (a7)+,b_gap(a5) * poof! line's gone.
bsr dirty * set modified flags
rts
*****************************************************************
del_word:
move.l b_gap(a5),-(a7) * Save gap pointer
bsr w_right * move cursor one word right
move.l (a7)+,b_gap(a5) * restore pointer, word vanishes
bsr dirty * set modified flags
rts
*****************************************************************
* PREFIX - Allows human to inser next char typed as literal
prefix:
bsr _getkey * take the next keystroke as-is
bra in_chr * insert whatever comes in
*****************************************************************
ret:
move.b #10,d0 * load up a newline
bra in_chr * go insert it
*****************************************************************
toggle:
not.w insert(a5) * complement insert toggle
rts
*****************************************************************
line_ins:
move.l e_gap(a5),a0 * get begin gap pointer
cmp.l b_gap(a5),a0 * see if there's room
ble sk0_lns * jump if no room
move.b #10,-(a0) * put in newline
subq.l #1,e_gap(a5) * adjust end pointer
bsr dirty * set modified flags
rts * exit
sk0_lns:
move.w #2,ed_err(a5) * error 2 - no more room
rts
*****************************************************************
ins_chr:
cmp.b #$20,d0 * check if char out of range
blt sk1_ins * if out, goto error
in_chr:
tst.w insert(a5) * is insert toggle on?
bne sk2_ins * jump if yes
move.l e_gap(a5),a0 * get end-of-gap address
cmp.l e_buf(a5),a0 * check if at end of buffer
bgt sk2_ins * yes, go insert
cmp.b #10,(a0) * see if next char is newline
beq sk2_ins * yes, go insert
move.l b_gap(a5),a0 * we need to replace...
move.b d0,(a0) * emplace new character
addq.l #1,b_gap(a5) * move begin gap pointer
addq.l #1,e_gap(a5) * move end gap pointer
bra sk4_ins * exit
sk2_ins:
move.l b_gap(a5),a0 * get begin gap pointer
cmp.l e_gap(a5),a0 * look see if there's room
bge sk3_ins * jump if no room
move.b d0,(a0) * insert character
addq.l #1,b_gap(a5) * move gap pointer
cmp.b #10,d0 * check for newline
bne sk4_ins * skip if not
addq.w #1,log_lin(a5) * increment logical line count
sk4_ins:
bsr dirty * set modified flags
rts * That's it.
sk1_ins:
move.w #1,ed_err(a5) * error #1 - char out of range
rts
sk3_ins:
move.w #2,ed_err(a5) * error #2 - no room
rts
*****************************************************************
* ISDELIM - returns TRUE if char in D0 matches delimiter list
isdelim:
move.l #delim,a0 * get delimiter list address
move.w #d_cnt,d1 * get delimiter count
lp0_dm:
cmp.b (a0)+,d0 * look for a match
beq d_true * found one, jump out
dbra d1,lp0_dm * check all cases
clr.w d0 * return FALSE
rts
d_true:
move.w #$FFFF,d0 * return TRUE
rts
delim: dc.b 9,10,' ,.-+/><()'
d_cnt equ *-delim
dc.w 0
*****************************************************************
* SOL - moves cursor to start of line
sol:
bsr left * try one char back
tst.b d0 * check if at top of file
beq sk0sol * jump out if at top of file
cmp.b #10,d0 * is this a newline?
bne sol * back up to start of this line
bsr right * re-adjust cursor
sk0sol:
rts
*****************************************************************
* EOL - moves cursor to end of line
eol:
bsr right * try one char forward
tst.b d0 * check if at end of file
beq sk0eol * jump out if at end of file
cmp.b #10,d0 * check for newline
bne eol * loop if not newline
bsr left * put cursor behind newline
sk0eol:
rts
*****************************************************************
* OUTLINE - moves cursor to current logical column
outline:
clr.w d2 * d2 is column accumulator
lp0_ol:
bsr right * try to move right
tst.b d0 * check if end-of file
beq sk1_ol * exit if end-of-file
cmp.b #10,d0 * check for end of line
beq sk0_ol * done if end-of-line
addq.w #1,d2 * start with one column
cmp.b #$20,d0 * see if control char
bge sk2_ol * if not, we're done with char
cmp.b #tab,d0 * is char a tab?
beq sk3_ol * jump if tab
subq.l #1,d2 * take away column for ctrl char
bra sk2_ol * make loop test
sk3_ol:
move.w d2,d0 * make a copy of column count
and.w #$0007,d0 * check for correct tab column
beq sk2_ol * if so, make loop test
addq.w #1,d2 * otherwise, add one space to col
bra sk3_ol * and keep expanding tab
sk2_ol:
cmp.w log_col(a5),d2 * are we far enough out?
ble lp0_ol * no, keep trying
sk0_ol:
bsr left * back up to correct position
sk1_ol:
rts
*****************************************************************
* ALIGN_SCR - Handles vertical cursor alignment. Puts the cursor
* on the screen if it's off.
align_scr:
move.l b_gap(a5),a0 * Get start of gap (cursor loc.)
cmp.l top_lef(a5),a0 * see if cursor's off top
bge sk0_as * jump if not off the top
lp0_as:
subq.l #1,a0 * start backing off
cmp.l b_buf(a5),a0 * don't go under start of file
beq sk1_as * jump if at start of file
cmp.b #10,(a0) * look for newline
bne lp0_as * not newline, try again
addq.l #1,a0 * ok, move past newline
sk1_as:
cmp.l b_buf(a5),a0 * one last check for nasties
bge sk5_as * no nasties
move.l b_buf(a5),a0 * start at top
sk5_as:
move.l a0,top_lef(a5) * reset top of screen
bra sk3_as * exit
sk0_as:
sub.l top_lef(a5),a0 * A0 is now chars-to-cursor
move.l a0,d0 * we need count in data register
move.l top_lef(a5),a0 * A0 is where we start looking
clr.w d1 * d1 will be newline count
bra sk2_as * do loop test before check
lp1_as:
cmp.b #10,(a0)+ * look for newlines
bne sk2_as * if not newline, don't care
addq.w #1,d1 * if newline, increment count
sk2_as:
dbra d0,lp1_as * loop test
sub.w w_rows(a5),d1 * see if more newlines than rows
blt sk3_as * if not, we're ok
move.l top_lef(a5),a0 * get starting point
lp3_as:
cmp.b #10,(a0)+ * we need to skip newlines
bne lp3_as * if not newline, we don't care
sk4_as:
dbra d1,lp3_as * loop for (d1+1) newlines
move.l a0,top_lef(a5) * save new top left corner
sk3_as:
rts
end